
import axios, { AxiosRequestConfig } from "axios";
import { createStore, Commit } from "vuex";
import { arrToObj, objToArr } from "./hook/helper";

// 返回的数据响应类型
export interface ResponseType<P = Record<string, unknown>> {
  code: number
  msg: string
  data: P
}
// 上传的图片数据类型
export interface UploadProps {
  _id?: string
  url?: string
  createdAt?: string
}
// 首页专栏数据类型
export interface ColumnProps {
  _id: string;
  title: string;
  avatar?: ImageProps;
  description: string;
}
// 图片数据类型
export interface ImageProps {
  _id?: string
  url?: string
  createdAt?: string
  fitUrl?: string;
}

// 专栏内文章的数据类型
export interface PostProps {
  _id?: string
  title: string
  excerpt?: string //摘要,简要显示内容
  content?: string
  image?: ImageProps | string
  createdAt?: string
  column: string;
  author?: string | UserProps; //文章详情下的author也是UserProps格式
  isHTML?: boolean
}

// 用户数据结构
export interface UserProps {
  isLogin: boolean;
  nickName?: string;
  _id?: string;
  column?: string;
  email?: string;
  avatar?: ImageProps;
  description?: string;
}

//错误信息
export interface GlobalErrorProps {
  status: boolean
  message?: string
}
// 全局通用的数据结构,便于操作
export interface GlobalDataProps {
  error: GlobalErrorProps
  token: string,
  isLoading: boolean
  columns: { data: ListProps<ColumnProps>; currentPage: number; total: number };
  posts: { data: ListProps<PostProps>; loadedColumns: string[] };
  user: UserProps
}
interface ListProps<P> {
  [id: string]: P
}

// async 和 await 是基于promises的语法糖，使异步代码更易于编写和阅读。
// 通过使用它们，异步代码看起来更像是老式同步代码，因此它们非常值得学习。
// 封装基于Promise的async和await的异步请求
// const getAndCommit = async (url: string, mutationsName: string, commit: Commit) => {
//   const { data } = await axios.get(url)
//   commit(mutationsName, data)
//   return data
// }

// // eslint-disable-next-line @typescript-eslint/no-explicit-any
// const PostAndCommit = async (url: string, mutationsName: string, commit: Commit, payload: any) => {
//   const { data } = await axios.post(url, payload)
//   commit(mutationsName, data)
//   return data
// }

//适应多种异步请求方法
const asyncAndCommit = async (url: string, mutationName: string, commit: Commit,
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  config: AxiosRequestConfig = { method: 'get' }, extraData?: any) => {
  const { data } = await axios(url, config)
  if (extraData) {
    commit(mutationName, { data, extraData })
  } else {
    commit(mutationName, data)
  }
  return data
}

const store = createStore<GlobalDataProps>({
  state: {
    error: { status: false },
    token: localStorage.getItem('token') || '',
    isLoading: false,
    columns: { data: {}, currentPage: 0, total: 0 },
    posts: { data: {}, loadedColumns: [] },
    user: { isLogin: false }
  },
  //发出指令
  actions: {
    // 获取首页专栏
    fetchColumns({ state, commit }, params = {}) {
      const { currentPage = 1, pageSize = 6 } = params
      // if (!state.columns.isLoaded) {
      //   return asyncAndCommit('/columns', 'fetchColumns', commit)
      // }
      if (state.columns.currentPage < currentPage) {
        return asyncAndCommit(`/columns?currentPage=${currentPage}&pageSize=${pageSize}`, 'fetchColumns', commit)
      }
    },
    // 获取专栏详情头
    fetchColumn({ state, commit }, cid) {
      if (!state.columns.data[cid]) {
        return asyncAndCommit(`/columns/${cid}`, 'fetchColumn', commit)
      }
    },

    // 获取专栏下的文章
    fetchPostsByColumn({ state, commit }, cid) {
      if (!state.posts.loadedColumns.includes(cid)) {
        return asyncAndCommit(`/columns/${cid}/posts`, 'fetchPostsByColumn', commit, { method: 'get' }, cid)
      }
    },

    //获取单个文章
    fetchPost({ state, commit }, pid) {
      const currentPost = state.posts.data[pid]
      if (!currentPost || !currentPost.content) {
        return asyncAndCommit(`/posts/${pid}`, 'fetchPost', commit)
      } else {
        return Promise.resolve({ data: currentPost })
      }
    },

    //登录
    login({ commit }, payload) {
      return asyncAndCommit('/user/login', 'login', commit, { method: 'post', data: payload })
    },

    //创建文章
    createPost({ commit }, payload) {
      return asyncAndCommit('/posts', 'createPost', commit, { method: 'post', data: payload })
    },

    //更新文章
    updatePost({ commit }, { id, payload }) {
      return asyncAndCommit(`/posts/${id}`, 'updatePost', commit, {
        method: 'patch',
        data: payload
      })
    },
    //删除文章
    deletePost({ commit }, id) {
      return asyncAndCommit(`/posts/${id}`, 'deletePost', commit, {
        method: 'delete',
      })
    },

    //获取用户信息
    fetchCurrentUser({ commit }) {
      return asyncAndCommit('/user/current', 'fetchCurrentUser', commit)
    },
    //使用actions异步,需要先登录再获取用户信息
    loginAndFetch({ dispatch }, loginData) {
      return dispatch('login', loginData).then(() => {
        return dispatch('fetchCurrentUser')
      })
    },

    updateColumn({ commit }, { id, payload }) {
      return asyncAndCommit(`/column/${id}`, 'updateColumn', commit, { method: 'patch', data: payload })
    },

    updateUser({ commit }, { id, payload }) {
      return asyncAndCommit(`/user/${id}`, 'updateUser', commit, { method: 'patch', data: payload })
    }

  },
  //得到指令操作数据
  mutations: {
    // login(state) {
    //   state.user = { ...state.user, isLogin: true, name: 'SkyMirrors' }
    // },
    createPost(state, newPost) {
      state.posts.data[newPost._id] = newPost
    },
    // 获取首页专栏数据
    fetchColumns(state, rawData) {
      const { data } = state.columns
      const { list, count, currentPage } = rawData.data
      state.columns = {
        data: { ...data, ...arrToObj(list) },
        total: count,
        currentPage: currentPage * 1
      }
    },

    // 获取专栏详情头
    fetchColumn(state, rawData) {
      state.columns.data[rawData.data._id] = rawData.data
    },

    // 获取专栏下的文章
    fetchPostsByColumn(state, { data: rawData, extraData: columnId }) {
      state.posts.data = { ...state.posts.data, ...arrToObj(rawData.data.list) }
      state.posts.loadedColumns.push(columnId)
    },

    //获取单个文章
    fetchPost(state, rawData) {
      state.posts.data[rawData.data._id] = rawData.data
    },

    // 更新单个文章
    updatePost(state, { data }) {
      state.posts.data[data._id] = data
    },
    // 删除单个文章
    deletePost(state, { data }) {
      delete state.posts.data[data._id]
    },

    // 请求的Loading
    setLoading(state, status) {
      state.isLoading = status
    },

    //获取用户信息
    fetchCurrentUser(state, rawData) {
      state.user = { isLogin: true, ...rawData.data }
    },

    setError(state, e: GlobalErrorProps) {
      state.error = e
    },
    // 登录
    login(state, rawData) {
      const { token } = rawData.data
      state.token = token
      localStorage.setItem('token', token)
      axios.defaults.headers.common.Authorization = `Bearer ${token}`
    },

    // 更新个人专栏
    updateColumn(state, { data }) {
      state.columns.data[data._id] = data
    },

    // 更新个人信息
    updateUser(state, { data }) {
      state.user = { isLogin: true, ...data }
    },

    //退出登录
    logout(state) {
      state.token = ''
      state.user = { isLogin: false }
      localStorage.removeItem('token')
      delete axios.defaults.headers.common.Authorization
    }

  },
  getters: {
    getColumns: (state) => {
      return objToArr(state.columns.data)
    },
    // 根据专栏ID查专栏 用于展示专栏详情头
    getColumnById: (state) => (id: string) => {
      return state.columns.data[id]
    },
    // 根据专栏ID查文章列表 用于展示属于某个专栏的文章列表
    getPostsByCid: (state) => (cid: string) => {
      return objToArr(state.posts.data).filter(post => post.column === cid)
    },
    // 根据文章ID查文章 用于展示文章详情
    getCurrentPost: (state) => (pid: string) => {
      return state.posts.data[pid]
    }
  }
})
export default store